package com.yilin.platform.service.impl.user;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yilin.platform.base_core.application.AppUtil;
import com.yilin.platform.base_core.application.BaseCode;
import com.yilin.platform.base_core.application.PageData;
import com.yilin.platform.base_core.commons.entity.AuthStatus;
import com.yilin.platform.base_core.commons.entity.AuthStatusData;
import com.yilin.platform.base_core.commons.exception.BusinessException;
import com.yilin.platform.base_core.commons.utils.ArrayUtil;
import com.yilin.platform.base_core.commons.utils.StringUtil;
import com.yilin.platform.base_core.commons.utils.constant.HttpConstant;
import com.yilin.platform.base_core.components.redis.RedisClient;
import com.yilin.platform.base_core.components.redis.RedisKeys;
import com.yilin.platform.base_core.tools.QueryUtil;
import com.yilin.platform.entity.enums.user.OrganType;
import com.yilin.platform.entity.enums.user.RoleType;
import com.yilin.platform.entity.enums.user.UserType;
import com.yilin.platform.entity.system.Jurisdiction;
import com.yilin.platform.entity.system.OperateLog;
import com.yilin.platform.entity.user.Account;
import com.yilin.platform.entity.user.Authority;
import com.yilin.platform.entity.user.Organize;
import com.yilin.platform.entity.user.auth.DrivingLicense;
import com.yilin.platform.entity.user.auth.IdCard;
import com.yilin.platform.entity.user.auth.QualificationCert;
import com.yilin.platform.mapper.user.AccountMapper;
import com.yilin.platform.service.impl.system.JurisdictionService;
import com.yilin.platform.service.user.IAccountService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
@Service
@Transactional
public class AccountService extends ServiceImpl<AccountMapper, Account> implements IAccountService {

    @Resource
    private AccountMapper accountMapper;
    @Resource
    private JurisdictionService jurisdictionService;
    @Resource
    private AuthorityService authorityService;
    @Resource
    private OrganizeService organizeService;
    @Resource
    private AuthService authService;
    /**
     * 员工注册
     */
    @Override
    public Account employeeRegister(Organize organize, Account employee, String[] jurisdictionIds) {
        /// ### 检查账户信息是否存在
        Account extAccount = this.getAccountByUsername(employee.getUsername());
        if (extAccount != null) throw new BusinessException("注册的账号已存在，不要重复注册！");
        if (employee.getPhone() != null) {
            Account pheAccount = this.getAccountByPhone(employee.getPhone(), organize.getUserType());
            if (pheAccount != null) throw new BusinessException("该手机号已被注册！请直接登录或更换手机号");
        }
        // ### 如果存在手机号相同的已删除账号，采用账户覆盖，不重新建立账户，部分信息，如认证功能会得到恢复
        List<Account> phoneAccList = getLogicAccountByPhone(employee.getPhone());
        if (phoneAccList.size() > 0) {
            employee.setId(ArrayUtil.first(phoneAccList).getId());
            accountMapper.recoveryById(employee.getId());
        }
        // #### 初始化信息
        employee.setOrganizeId(organize.getId());
        employee.setOrganizeName(organize.getOrganizeName());
        employee.setUserType(organize.getUserType());
        employee.setOrganType(organize.getOrganType());
        employee.setSuperiorPlatId(organize.getSuperiorPlatOrganizeId());
        employee.setSuperiorPlatName(organize.getSuperiorPlatOrganizeName());
        employee.setOrganizeManagerUserId(organize.getManagerUserId());
        employee.setOrganizeManagerUserName(organize.getManagerUserName());
        employee.setUserState(Account.UserState.enable);
        // #### 发送初始化密码
        String initPassword = employee.getPassword();
//        String msg = "您的管理员：%s 已成功为您注册%s成员账户，登录账号：%s，初始密码：%s，请及时登录并完成密码修改！";
//        String fmtMsg = String.format(msg, organize.getManagerUserName(), organize.getOrganizeName(), employee.getUsername(), initPassword);
//        messageRemote.sendPhoneMessage(employee.getPhone(), fmtMsg);
        // #### 注册完成
        employee.setPassword(AppUtil.md5(initPassword));
        employee.setAddUserId(organize.getManagerUserId());
        employee.setCreateTime(new Date());
        if (employee.getId() == null) accountMapper.insert(employee);
        else accountMapper.updateById(employee);
        if(jurisdictionIds!=null){
            List<Jurisdiction> jurisdictionList=jurisdictionService.getJurisdictionListByIds(jurisdictionIds);
            if(jurisdictionList!=null&& !jurisdictionList.isEmpty()){
                authorityService.saveAuthority(employee,jurisdictionList);
            }
        }
        return employee;
    }
    //----------------------------------------------账户变更区--------------------------------------------------
    /**
     * 更新账户2
     */
    @Override
    public void updateAccount(Account loginUser, Account param, Account localAccount) {
        if (param.getUserState() != null) localAccount.setUserState(param.getUserState());
        if (StringUtil.isNotEmpty(param.getUsername())) {
            Account other = accountMapper.selectOne(new QueryWrapper<Account>().eq("username", param.getUsername()));
            if (other != null && !other.getId().equals(localAccount.getId()))
                throw new BusinessException("您修改的账号已被占用，请重新更换");
            localAccount.setUsername(param.getUsername());
        }
        //------------------------------基本型信息-------------------------------------
        if (StringUtil.isNotEmpty(param.getPhone())) localAccount.setPhone(param.getPhone());
        if (StringUtil.isNotEmpty(param.getEmail())) localAccount.setEmail(param.getEmail());
        if (StringUtil.isNotEmpty(param.getWechatId())) localAccount.setWechatId(param.getWechatId());
        if (StringUtil.isNotEmpty(param.getAddress())) localAccount.setAddress(param.getAddress());
        if (StringUtil.isNotEmpty(param.getName())) localAccount.setName(param.getName());
        if (StringUtil.isNotEmpty(param.getAvatar())) localAccount.setAvatar(param.getAvatar());

        //-------------------------------API秘钥---------------------------------------
        if (localAccount.getRoleType() == RoleType.api && StringUtil.isNotEmpty(param.getPublicKey())) {
            localAccount.setPublicKey(param.getPublicKey());
            String secretKey = RedisClient.getInstance().hget(RedisKeys.ACCOUNT_API_PAIR_KEY, param.getPublicKey());
            localAccount.setSecretKey(secretKey);
        }
        if (localAccount.getRoleType() == RoleType.manager) {
            Organize organize = organizeService.getOrganizeById(localAccount.getOrganizeId());
            if (StringUtil.isNotEmpty(param.getName())) organize.setManagerUserName(param.getName());
            if (StringUtil.isNotEmpty(param.getAvatar())) organize.setManagerUserAvatar(param.getAvatar());
            if (StringUtil.isNotEmpty(param.getPhone())) organize.setManagerUserPhone(param.getPhone());
            organizeService.updateById(organize);
        }
        localAccount.setUpdateUserId(loginUser.getId());
        localAccount.setUpdateTime(new Date());
        accountMapper.updateById(localAccount);
    }
    /**
     * 安全操作 安全密码次数验证
     */
    @Override
    public void verifySvePassword(Account loginUser, String savePassword) {
        Account account = this.getAccountById(loginUser.getId());
        if (account.getSafePassword() == null) {
            throw new BusinessException(BaseCode.NO_PASS_ERR, "你没有设置安全密码！");
        }
        if (account.getSafeDisabled()) {
            throw new BusinessException(account.getSafeFailReason());
        }
        if (!AppUtil.md5(savePassword).equals(account.getSafePassword())) {
            account.setSafeFailCount(account.getSafeFailCount() + 1);
            if (account.getSafeFailCount() <= 3) {
                String errTip = "安全密码错误，您今日已输错%s次，超过3次将被禁用操作";
                accountMapper.updateById(account);
                throw new BusinessException(String.format(errTip, account.getSafeFailCount()));
            }
            // ### 超过三次 禁用操作
            account.setSafeFailCount(0);//禁用账户，还原次数
            account.setSafeDisabled(true);
            account.setSafeFailReason("密码输入错误超过3次，已被禁用安全操作");
            accountMapper.updateById(account);
            throw new BusinessException("您今日输错安全密码超过3次，已被禁用安全操作");
        }
    }
    /**
     * SQL更新账户
     */
    @Override
    public Account saveOrUpdateAccount(Account account, Account loginUser) {
        if (account.getId() != null) {
            account.setUpdateUserId(loginUser.getId());
            account.setUpdateTime(new Date());
        } else {
            account.setAddUserId(loginUser.getId());
            account.setCreateTime(new Date());
        }
        saveOrUpdate(account);
        return account;
    }
    @Override
    public void updateAccountAndOrganize(Account loginUser, Account account, Organize organize) {
        if (organize.getId() != null) {
            if (loginUser.getRoleType() != RoleType.manager) {
                throw new BusinessException("您没有权限修改");
            }
            Organize organizeOld = organizeService.getOrganizeById(organize.getId());
            organizeOld.setOrganizeTel(organize.getOrganizeTel());
            organizeOld.setAddress(organize.getAddress());
            organizeOld.setOrganizeLogo(organize.getOrganizeLogo());
            organizeOld.setIntroduction(organize.getIntroduction());
            organizeOld.setUpdateUserId(loginUser.getId());
            organizeOld.setUpdateTime(new Date());
            organizeService.updateById(organizeOld);
        }
        Account accountOld = getAccountById(account.getId());
        accountOld.setAvatar(account.getAvatar());
        accountOld.setEmail(account.getEmail());
        accountOld.setAddress(account.getAddress());
        accountMapper.updateById(accountOld);
    }

    /***
     * 转让管理员
     * */
    @Override
    public void transferManager(Account manager, Account account) {
        Organize organize = organizeService.getOrganizeById(manager.getOrganizeId());
        //第二步：修改组织信息
        organize.setManagerUserId(account.getId());
        organize.setManagerUserName(account.getName());
        organize.setManagerUserPhone(account.getPhone());
        organize.setManagerUserEmail(account.getEmail());
        //第三步：修改所有员工管理员
        List<Account> employeeList = getEmployeeByOrganizeId(organize.getId());
        for (Account employee : employeeList) {
            employee.setOrganizeManagerUserId(account.getId());
            employee.setOrganizeManagerUserName(account.getName());
            updateById(employee);
        }
        //第四步：修改集团下属集团上级管理员
        List<Organize> organizeList = organizeService.getGroupOrganizeList(organize.getId());
        for (Organize childOrganize : organizeList) {
            childOrganize.setGroupOrganizeManagerUserId(account.getId());
            childOrganize.setGroupOrganizeManagerUserName(account.getName());
            organizeService.updateById(childOrganize);
        }
        //第五步：重置身份证认证，清除电子签名和税务认证，
        IdCard idCard = authService.getIdCardByUserId(account.getId());
        if (idCard != null) {
            idCard.setAuthStatus(AuthStatus.notApply);
            authService.saveIdCardAuth(account, idCard);
        }
        updateById(manager);
        updateById(account);
        organizeService.updateById(organize);
    }
    /**
     * 批量账户找查 组织获取员工
     */
    @Override
    public List<Account> getEmployeeByOrganizeId(String organizeId) {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("organize_id", organizeId);
        queryWrapper.orderByAsc("role_type");
        List<Account> accounts = accountMapper.selectList(queryWrapper);
        for (Account account : accounts) { //放在控制层
            List<AuthStatusData> authStatusDataList = authService.getUserAuthStatus(account);
            List<Authority> authorityList=authorityService.getAuthorityListByyAccountId(account.getId());
            account.setAuthorityList(authorityList);
            account.setAuthStatusList(authStatusDataList);
            account.setSafePassword(null);
            account.setPassword(null);
            account.setSecretKey(null);
            account.setFingerprintSecretKey(null);
        }
        return accounts;
    }
    /**
     * 账户注销
     */
    @Override
    public void scrapAccount(Account manager, Account account) {
        //需逻辑删除所有证件数据
        IdCard idCard = authService.getIdCardByUserId(account.getId());
        if (idCard != null) authService.deleteIdCardById(idCard);
        DrivingLicense drivingLicense = authService.getDrivingLicenseByUserId(account.getId());
        if (drivingLicense != null) authService.deleteDrivingLicenseById(drivingLicense);
        QualificationCert qualificationCert = authService.getQualificationCertByUserId(account.getId());
        if (qualificationCert != null) authService.deleteDrivingLicenseById(drivingLicense);
        //实体中含有逻辑删除字段，此数据不会被真实删除
        authorityService.deleteAuthorityListByAccountId(account.getId());
        accountMapper.deleteById(account);
        if (account.getRoleType() == RoleType.employee) {
            String msg = "尊敬的用户您好，您的管理员：%s 已将你移出组织：%s，您的账户已被强制注销，下次使用时需要重新注册账号！";
            String fmtMsg = String.format(msg, manager.getName(), manager.getOrganizeName());
//            messageRemote.sendPhoneMessage(account.getPhone(), fmtMsg);
        }
    }
    /**
      * 新 登录授权
     */
    @Override
    public void login(Account account, HttpServletRequest request) {
        account.setLoginIps(AppUtil.getIp(request));
        account.setLoginCount(account.getLoginCount() + 1); // 登录次数加1
        account.setLastLoginTime(new Date());
        account.setUpdateTime(new Date());
        accountMapper.updateById(account);

        //生成登录日志
        String customerIp = AppUtil.getIp(request);
        boolean mobile = request.getHeader(HttpConstant.MOBILE) != null;
        OperateLog operateLog = new OperateLog();
        operateLog.setOptUserId(account.getId());
        operateLog.setOptToken(account.getToken());
        operateLog.setOptIp(customerIp);
        operateLog.setSuperiorPlatId(account.getSuperiorPlatId());
        operateLog.setOptUserName(account.getName() == null ? account.getUsername() : account.getName());
        operateLog.setOptDeviceType(mobile ? OperateLog.DeviceType.mobile : OperateLog.DeviceType.web);
        operateLog.setOperateSite(request.getRequestURI());
        operateLog.setOptTime(new Date());
//        operateLogRepository.save(operateLog);
    }
    /**
     * 根据用户类型获取pushIds
     */
    @Override
    public String[] getPushIdsByUserType(Account loginUser, UserType userType) {
        List<String> pushIdsByUserType = accountMapper.getPushIdsByUserType(loginUser, userType);
        return pushIdsByUserType.toArray(new String[0]);
    }
//    -------------------------------------查询区----------------------------------
    /**
     * 账户找查03: 微信ID
     */
    @Override
    public Account getAccountByWechatId(String wechatId) {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("wechat_id", wechatId);
        return accountMapper.selectOne(queryWrapper);
    }
    /**
     * 账户找查03: 用户管理员
     */
    @Override
    public List<Account> getAccountByManager() {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_type", RoleType.manager);
        return accountMapper.selectList(queryWrapper);
    }

    /**
     * 账户找查 ID
     */
    @Override
    public Account getAccountById(String accountId) {
        return accountMapper.selectById(accountId);
    }

    @Override
    public Account getAccountByUsername(String username) {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        return accountMapper.selectOne(queryWrapper);
    }
    /**
     * 账户找查 手机号
     */
    @Override
    public Account getAccountByPhone(String phone, UserType userType) {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", phone);
        queryWrapper.eq("user_type", userType.index);
        return accountMapper.selectOne(queryWrapper);
    }
    /**
     * 账户找查 手机号
     */
    @Override
    public Account getAccountPhone(String phone) {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone", phone);
        List<Account> accounts = accountMapper.selectList(queryWrapper);
        if(accounts==null||accounts.isEmpty())return null;
        if(accounts.size()>1)throw  new BusinessException("手机号码存在多个");
        return accounts.get(0);
    }

    /**
     * 账户找查 批量获取Account
     */
    @Override
    public List<Account> getAccountListByIds(String[] accountIds) {
        List<String> stringList = ArrayUtil.initList(accountIds);
        return accountMapper.selectBatchIds(stringList);
    }
    /***
     * 账户找查 系统顶级管理用户
     * */
    @Override
    public Account getSystemAdminUser() {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_type", UserType.adminUser.index);
        queryWrapper.eq("role_type", RoleType.manager.index);
        return accountMapper.selectOne(queryWrapper);
    }
    /***
     * 账户找查 平台管理用户
     * */
    @Override
    public Account getSystemPlatformUser() {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_type", UserType.platformUser.index);
        queryWrapper.eq("role_type", RoleType.manager.index);
        return accountMapper.selectOne(queryWrapper);
    }
    /**
     * 账户找查 获取用户所有下级账户信息
     */
    @Override
    public PageData<Account> getAccountChildPage(Account logAccount, Account query, Integer start, Integer limit) {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        QueryUtil.buildOrganizeIdOrSuperiorPlatIdWrapper(queryWrapper,logAccount);
        return accountMapper.selectPage(new PageData<>(start, limit), queryWrapper);
    }

    /**
     * 账户找查 获取司机列表
     */
    @Override
    public PageData<Account> getAccountDriverPage(Account logAccount, Account query, Integer start, Integer limit) {
        QueryWrapper<Account> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_type", UserType.truckerUser.index);
        queryWrapper.eq("organ_type", OrganType.individual.index);
        QueryUtil.buildOrganizeIdOrSuperiorPlatIdWrapper(queryWrapper,logAccount);
        return accountMapper.selectPage(new PageData<>(start, limit), queryWrapper);
    }


    /**
     * 根据手机号获取已经逻辑删除的账户
     * 全网唯一一个可以使用删除数据恢复的方法
     */
    @Override
    public List<Account> getLogicAccountByPhone(String phone) {
        return accountMapper.getLogicAccountByPhone(phone);
    }
}
